Skip to content

feat(cli): allow generic file uploads including zip - #4880

Open
Trevongit wants to merge 4 commits into
block:mainfrom
Trevongit:feat/cli-m1-generic-file-upload
Open

feat(cli): allow generic file uploads including zip#4880
Trevongit wants to merge 4 commits into
block:mainfrom
Trevongit:feat/cli-m1-generic-file-upload

Conversation

@Trevongit

Copy link
Copy Markdown

Summary

  • Widen buzz-cli upload MIME policy so agent co-lab can attach zip skill packs and other safe generic files (pdf, text, json, common archives/docs).
  • Keep a danger denylist aligned with buzz-media (HTML/JS/SVG, native executables/installers); images and video/mp4 unchanged.
  • Generic uploads use a 100 MB cap (matches relay default BUZZ_MAX_FILE_BYTES).

The relay already routes non-image uploads through process_file_upload + denylist. The CLI was the choke (unsupported file type: application/zip).

Dogfood

  • Unit tests for allow/block/size tiers
  • Live zip upload to a private My Groundfeed via rebuilt CLI succeeded

Test plan

  • cargo test -p buzz-cli --lib upload_
  • CI full suite
  • Optional: buzz upload file --file pack.zip against a local or private relay

Agent co-lab was blocked on skill packs because buzz-cli only allowed
image/* and video/mp4. The relay already accepts generic Blossom uploads
via a danger denylist (HTML/JS/SVG/executables). Align the CLI with that
policy so zip/pdf/text and similar types work while unsafe types stay
blocked.

Add unit coverage for allow/block and size tiers (100MB generic).

Signed-off-by: Trevor P <trev2005@gmail.com>
@Trevongit
Trevongit requested a review from a team as a code owner August 5, 2026 11:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1562cc9cda

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if mime.starts_with("audio/") {
return false;
}
!BLOCKED_FILE_MIMES.contains(&mime)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Render generic attachments as links

Allowing every non-blocklisted MIME here also enables buzz messages send --file <pdf|zip|txt>, but that send path still formats every uploaded non-video descriptor as ![image](url) in crates/buzz-cli/src/commands/messages.rs:622-626. Desktop's generic file renderer keys on a plain [filename](url) link with matching non-media imeta, so these newly allowed attachments render as broken inline images instead of download cards; update the CLI message formatting before broadening this allowlist.

Useful? React with 👍 / 👎.

@michegz

michegz commented Aug 5, 2026

Copy link
Copy Markdown

Independent prod verification, in case it's useful for review — I hit the exact unsupported file type: application/pdf this patches against a live communities.buzz.xyz deployment (buzz upload file --file cattle.pdf on a 180 KB, 7-page document). To sanity-check the fallback story this PR relies on, I bypassed the CLI and signed a Blossom kind:24242 event directly to PUT /upload: returns 200 OK with "type":"application/pdf", and buzz media get round-trips byte-identical (SHA-256 match). So the server-side `validate_file_content` + `BLOCKED_FILE_MIME_TYPES` filter this PR trusts is doing its job in production — the CLI's `ALLOWED_MIMES` really is the sole choke on communities.buzz.xyz today.

One thing I liked reviewing the diff: `is_upload_mime_allowed()` mirrors the relay's denylist rather than hand-rolling a parallel allowlist, so the CLI won't silently drift out of sync the next time `buzz-media` adds a MIME. That's a nicer factoring than a static list would have been.

Trevongit added a commit to Trevongit/buzz that referenced this pull request Aug 6, 2026
Codex P2 on block#4880: after widening upload MIME types, `messages send --file`
still emitted `![image](url)` for every non-video blob. Desktop FileCard
expects plain `[filename](url)` plus imeta `filename` for zip/pdf/txt.

Match Desktop formatImetaMediaLine: images/video stay inline; generic files
and agent/team snapshot PNGs use markdown links; escape label metacharacters;
include basename on imeta tags.

Signed-off-by: Trevor P <trev2005@gmail.com>
Codex P2 on block#4880: after widening upload MIME types, `messages send --file`
still emitted `![image](url)` for every non-video blob. Desktop FileCard
expects plain `[filename](url)` plus imeta `filename` for zip/pdf/txt.

Match Desktop formatImetaMediaLine: images/video stay inline; generic files
and agent/team snapshot PNGs use markdown links; escape label metacharacters;
include basename on imeta tags.

Signed-off-by: Trevor P <trev2005@gmail.com>
@Trevongit
Trevongit force-pushed the feat/cli-m1-generic-file-upload branch from 1d36957 to 5fb4c1a Compare August 6, 2026 14:37
@Trevongit

Copy link
Copy Markdown
Author

Addressed the Codex P2 (generic attachments as links):

  • messages send --file now formats via format_attachment_markdown (Desktop formatImetaMediaLine parity):
    • image/*![image](url) (except *.agent.png / *.team.png snapshots → file link)
    • video/*![video](url)
    • generic (zip/pdf/txt/…) → [filename](url) with label escaping
  • imeta tags now include filename <basename> for FileCard labels

Pushed on this PR as fix(cli): format generic file attachments as download links.

After routing `messages send --file` through `build_imeta_tag_with_filename`,
the thin `build_imeta_tag` wrapper had no non-test caller, so the plain lib
build tripped `-D warnings` dead_code and failed the Rust Lint CI gate. Fold
its doc comment into `build_imeta_tag_with_filename` and have the test call the
`(&d, None)` form directly.

Signed-off-by: Ravneet Arora <rarora@squareup.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
ravarora2
ravarora2 previously approved these changes Aug 7, 2026

@ravarora2 ravarora2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ravarora2 ravarora2 added the triage-ready Appropriate for agentic review label Aug 7, 2026

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review submitted by Carl on Wes's behalf.

The upload policy and generic-link formatting are sound, but the new filename field needs to obey the relay validation it targets before this can merge.

[P2] Validate or omit relay-invalid basenames before publishingbuild_imeta_tag_with_filename currently appends every non-empty basename unchanged. On Unix, filenames may contain \\ and control characters (including newlines); the relay explicitly rejects either in crates/buzz-relay/src/handlers/imeta.rs (imeta filename must not contain path separators or control characters). cmd_send_message now adds this field for every attachment, so a previously sendable image such as report\\final.png uploads successfully and then the message publish fails, leaving an orphaned blob. Please apply the relay's 1–255-byte / no-separator / no-control validation before upload or omit the filename field when invalid, and cover the invalid-basename case. The markdown label should follow the same safe fallback if the field is omitted.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blocking regression: the new filename field is emitted without applying the relay's filename constraints, so valid local files can upload successfully but then make messages send --file fail at event ingest. Please sanitize the basename using the same contract as Desktop (strip either path separator, remove controls, bound to 255 bytes/characters as required, and provide a fallback), and use that same sanitized label for both imeta and markdown. The current Windows CI failure is in unrelated buzz-dev-mcp shell timeout tests, not this diff.

Comment thread crates/buzz-cli/src/client.rs Outdated
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(name);
tag.push(format!("filename {base}"));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: This does not actually guarantee a relay-valid filename. On Unix, Path::file_name() leaves bad\\name.zip unchanged; control characters are also retained, and names longer than 255 are unbounded. The relay rejects all three (crates/buzz-relay/src/handlers/imeta.rs:140-155), while Desktop explicitly strips both separator styles, controls, and caps the label (desktop/src-tauri/src/commands/media.rs:138-153). Because cmd_send_message now attaches filename to every upload, even an otherwise valid image with such a local name uploads first and then fails message ingest—a regression from the old filename-free tag. Please centralize a sanitizer matching the relay contract and use its result for both this field and the markdown label. Add cases for backslashes, controls, and oversized/multibyte names.

@wesbillman
wesbillman dismissed their stale review August 7, 2026 23:12

Duplicate of the later changes-requested review; both identified the same filename-validation blocker. Keeping the more precise review as the single actionable request.

Wes requested changes on block#4880: Path::file_name alone left backslashes,
controls, and oversize names intact, so Blossom upload could succeed while
messages send --file failed at event ingest.

Add sanitize_filename (strip / and \, drop controls, bound 255 UTF-8 bytes,
fallback "file") and use it for both imeta filename and markdown labels.

Signed-off-by: Trevor P <trev2005@gmail.com>
@Trevongit

Copy link
Copy Markdown
Author

Thanks for the careful review, Wes (and Carl).

Agree on the blocking point: we should sanitize basenames to the same contract as Desktop / relay imeta (strip path separators / and \, remove controls, cap at 255 UTF-8 bytes, fallback file) and use that for both the filename field and the markdown label so Blossom upload can’t succeed while messages send --file fails at event ingest.

Addressed in 8b06342a6:

  • New sanitize_filename in crates/buzz-cli/src/client.rs (mirrors Desktop sanitize_filename + relay byte bound)
  • Used for imeta filename and for generic attachment markdown labels
  • Unit tests for traversal, backslash basenames, controls, oversize, and multibyte bound

Windows CI timeout remains out of scope for this diff (as you noted). Ready for another look when you have a moment — re-requesting review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-ready Appropriate for agentic review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants